package com.ysy.logistics.service.system.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ysy.common.resp.ResultData;
import com.ysy.common.resp.ReturnCodeEnum;
import com.ysy.common.util.SaltMD5Util;
import com.ysy.logistics.entities.system.SysRole;
import com.ysy.logistics.entities.system.SysUser;
import com.ysy.logistics.entities.system.UserRole;
import com.ysy.logistics.entities.system.dto.SysUserDTO;
import com.ysy.logistics.entities.system.MenuNode;
import com.ysy.logistics.entities.system.RoleMenu;
import com.ysy.logistics.entities.system.vo.LoginVO;
import com.ysy.logistics.entities.system.vo.RegisterVO;
import com.ysy.logistics.mapper.system.SysRoleMapper;
import com.ysy.logistics.mapper.system.SysUserMapper;
import com.ysy.logistics.mapper.system.UserRoleMapper;
import com.ysy.logistics.mapper.system.MenuNodeMapper;
import com.ysy.logistics.mapper.system.RoleMenuMapper;
import com.ysy.logistics.service.system.SysUserService;
import com.ysy.logistics.util.PageInfo;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassDescription:
 * @Author:姚斯羽
 * @Create:2025/3/12 14:43
 **/
@Slf4j
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {
    @Resource
    private SysUserMapper sysUserMapper;
    @Resource
    private UserRoleMapper userRoleMapper;
    @Resource
    private SysRoleMapper sysRoleMapper;
    @Resource
    private MenuNodeMapper menuNodeMapper;
    @Resource
    private RoleMenuMapper roleMenuMapper;

    @Override
    public ResultData<SysUserDTO> login(LoginVO loginVO) {
        log.debug("登录参数：{}", loginVO);
        //参数判断
        if (StringUtils.isBlank(loginVO.getAccount()) || StringUtils.isBlank(loginVO.getPassport())) {
            return ResultData.fail(ReturnCodeEnum.USERNAME_OR_PASSWORD_ERROR.getCode(), "账号或密码不能为空");
        }
        //查询通过用户名
        LambdaQueryWrapper<SysUser> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(SysUser::getUsername, loginVO.getAccount());

        SysUser sysUser = getOne(lambdaQueryWrapper);


        //null 则返回错误
        if (Objects.isNull(sysUser)){
            return ResultData.fail(ReturnCodeEnum.USERNAME_OR_PASSWORD_ERROR);
        }
        //验证状态
        if (sysUser.getStatus() == 1) {
            return ResultData.fail(ReturnCodeEnum.USER_DISABLED);
        }
        //验证密码
        if(!SaltMD5Util.verifySaltPassword(loginVO.getPassport(), sysUser.getPassword())){
            return ResultData.fail(ReturnCodeEnum.USERNAME_OR_PASSWORD_ERROR);
        }

        //通过验证存储登录信息
        StpUtil.login(sysUser.getId());
        //封装用户信息
        SysUserDTO loginUser = SysUserDTO.convertToSysUserDTO(sysUser);
        loginUser.setToken(StpUtil.getTokenValue());

        return ResultData.success(loginUser);
    }

    @Override
    public ResultData<SysUserDTO> register(RegisterVO registerVO) {
        //判断用户名是否被使用
        LambdaQueryWrapper<SysUser> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.select(SysUser::getId)
                .eq(SysUser::getUsername, registerVO.getUsername());
        if (count(lambdaQueryWrapper) > 0) {
            return ResultData.fail("该用户名已被使用");
        }

        //构建用户对象
        SysUser sysUser = RegisterVO.convertToSysUser(registerVO);
        sysUser.setCreateTime(new Date());
        //保存用户
        if (save(sysUser)) {
            return ResultData.success(SysUserDTO.convertToSysUserDTO(sysUser));
        }
        return ResultData.fail(ReturnCodeEnum.RC500);
    }

    @Override
    public ResultData<String> existsBySysUser(SysUser sysUser) {
        if (Objects.isNull(sysUser)) {
            return ResultData.fail(ReturnCodeEnum.RC205);
        }
        //查询
        QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>(sysUser);
        if (count(queryWrapper) > 0) {
            return ResultData.success("存在该用户");
        }
        return ResultData.fail("不存在该用户");
    }

    @Override
    public ResultData<SysUserDTO> getUserInfoById(String id) {
        SysUser sysUser = getById(id);
        if (Objects.isNull(sysUser)){
            return ResultData.fail("不存在此用户");

        }
        SysUserDTO sysUserDTO = SysUserDTO.convertToSysUserDTO(sysUser);
        //查询用户角色
        LambdaQueryWrapper<UserRole> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserRole::getUserId, id);
        List<UserRole> userRoles = userRoleMapper.selectList(queryWrapper);
        if (!CollectionUtil.isEmpty(userRoles)){
            List<String> roleIds = userRoles.stream().map(UserRole::getRoleId).collect(Collectors.toList());

            List<SysRole> sysRoles = sysRoleMapper.selectByIds(roleIds);
            if (Objects.nonNull(sysRoles)){
                List<String> rolesName = sysRoles.stream().map(SysRole::getName).collect(Collectors.toList());
                sysUserDTO.setRolesName(rolesName);
            }
            //获取菜单
            LambdaQueryWrapper<RoleMenu> lqw = new LambdaQueryWrapper<>();
            lqw.select(RoleMenu::getMenuId).in(RoleMenu::getRoleId, roleIds);
            List<RoleMenu> roleMenus = roleMenuMapper.selectList(lqw);
            List<Long> menuIds = roleMenus.stream().map(RoleMenu::getMenuId).collect(Collectors.toList());
            //查询出用户有的菜单
            List<MenuNode> menuNodes = menuNodeMapper.selectByIds(menuIds);
            //取出顶级菜单
            List<MenuNode> topMap = menuNodes.stream().filter(menuNode -> menuNode.getParentId()==0).sorted(Comparator.comparingInt(MenuNode::getNum))
                    .collect(Collectors.toList());
            List<Long> collect = menuNodes.stream().filter(menuNode -> menuNode.getParentId()!=0).map(MenuNode::getId).collect(Collectors.toList());
            List<MenuNode> menuTree = getMenuTree(topMap, collect);
            sysUserDTO.setMenuVOTree(MenuNode.buildTree(menuTree));
        }

        return ResultData.success(sysUserDTO);
    }

    private List<MenuNode> getMenuTree(List<MenuNode> pMenu,List<Long> checkedMenuIds) {
        if (CollectionUtil.isEmpty(pMenu)|| CollectionUtil.isEmpty(checkedMenuIds)){
            return null;
        }
        for (int i = 0; i < pMenu.size(); i++) {
            MenuNode menuNode = pMenu.get(i);
            LambdaQueryWrapper<MenuNode> lqw = new LambdaQueryWrapper<>();
            lqw.eq(MenuNode::getParentId,menuNode.getId()).in(MenuNode::getId,checkedMenuIds).orderByAsc(MenuNode::getNum);
            List<MenuNode> menuNodes = menuNodeMapper.selectList(lqw);
            if (CollectionUtil.isNotEmpty(menuNodes)){
                getMenuTree(menuNodes,checkedMenuIds);

            }
            menuNode.setChildren(menuNodes);
        }
        return pMenu.stream().sorted(Comparator.comparingInt(MenuNode::getNum)).collect(Collectors.toList());
    }

    @Override
    public Page<SysUser> listByPage(PageInfo<SysUser> pageInfo) {
        return sysUserMapper.selectByPage(pageInfo.getPage(), pageInfo.getCriteria());
    }
}
